//##########################################################################
//#                                                                        #
//#                            CLOUDCOMPARE                                #
//#                                                                        #
//#  AUTEUR   : Daniel Girardeau-Montaut, doctorant (2003-2006)            #
//#  COPYRIGHT 2006 : EDF R&D / TELECOM PARIS (TSI)                        #
//#                                                                        #
//#  ATTENTION, CE CODE CORRESPOND A L'IMPLEMENTATION D'ALGORITHMES ET     #
//#  DE TRAITEMENTS SPECIFIQUES DE DONNEES DEVELOPPEES DANS LE CADRE       #
//#  D'UNE THESE (CONVENTION CIFRE) FINANCEE PAR EDF R&D ET ENCADREE PAR   #
//#  TELCOM PARIS (LABORATOIRE TSI). SA CONSULTATION ET SON UTILISATION    #
//#  SONT LIMITEES AUX SEULES PERSONNES AUTORISEES D'EDF R&D ET TELECOM    #
//#  PARIS. DE PLUS, SA DIFFUSION EST FORTEMENT DECONSEILLEE ETANT DONNE   #
//#  SON CARACTERE EXPERIMENTAL ET PARFOIS INCOMPLET. CE N'EST QU'UN PRO-  #
//#  TOTYPE ATTENDANT UNE STRUCTURATION ET UNE INSTRUMENTATION PROPRE,     #
//#  EN PARTICULIER AU NIVEAU DU MODELE OBJET ET DE LA DOCUMENTATION.      #
//#  LE COMPORTEMENT DES ALGORITHMES N'EST PAS GARANTI EN L'ETAT.          #
//#                                                                        #
//##########################################################################

#include "ObjFilter.h"

#include "../include/SimpleMesh.h"
#include "../include/SimpleCloud.h"
#include "../include/SimpleTriangle.h"
#include "../include/CCMiscTools.h"

#include <assert.h>

#define MAX_ASCII_FILE_LINE_LENGTH 1024

GenericIndexedMesh* ObjFilter::loadFile(char* fileName)
{
    //ouverture du fichier
    FILE *fp;
    if ((fp = fopen(fileName, "rt"))==NULL)
    {
		printf("[ObjFilter::loadModelFromObjFile] Error opening the file !\n");
        return NULL;
    }

	int j;
    PointCoordinateType P[3];

	bool isTextured,isNormed;
	unsigned lineReaded,facesReaded;

	//buffers
	char ligne[MAX_ASCII_FILE_LINE_LENGTH];
	char format[256];

	int maxNumberOfVertexPerPoly = 256;
	unsigned* face = new unsigned[maxNumberOfVertexPerPoly*3];
	memset(face,0,maxNumberOfVertexPerPoly*3*sizeof(unsigned));

	//liste initiale
	SimpleCloud* vertexes = new SimpleCloud();
	unsigned theoricNumberOfVertexes=0;

	//le mesh
	SimpleMesh* tri = new SimpleMesh(vertexes,true);
	unsigned theoricNumberOfFaces=0;

	isTextured = false;
	isNormed = false;
	lineReaded = 0;					//points lus
	facesReaded = 0;				//faces lues

	SimpleTriangle currentTriangle;

	while (fgets (ligne , MAX_ASCII_FILE_LINE_LENGTH , fp)!=NULL)
	{
		if (ligne[0]=='#')
		{
			//printf("%s",ligne); //commentaire
		}
		else if (ligne[0]=='v')
		{
			if (ligne[1]=='t') //vt = vertex texture
			{
				isTextured = true;
			}
			else if (ligne[1]=='n') //vn = vertex normal
			{
				isNormed = true;
			}
			else if ((ligne[1]==SPACE_ASCII_CODE)||(ligne[1]==TAB_ASCII_CODE)) //v = vertex
			{
				sscanf(ligne,"%s %f %f %f\n",format,P,P+1,P+2);
				if (lineReaded==theoricNumberOfVertexes)
				{
					theoricNumberOfVertexes+=MAX_NUMBER_OF_ELEMENTS_PER_CHUNK;
					vertexes->reserve(theoricNumberOfVertexes);
				}
				vertexes->addPoint(P);
				++lineReaded;
			}
		}
		else if (ligne[0]=='g') //nouvel objet
		{
			//on veut un seul mesh !
		}
		else if (ligne[0]=='f')
		{
			if ((ligne[1]==SPACE_ASCII_CODE)||(ligne[1]==TAB_ASCII_CODE)) //f = face
			{
				int car=2;
				int slash=0;
				int ind=0;

				while (ligne[car]>0)
				{
					if (ligne[car]=='/')
					{
						++slash;
					}
					else
					{
						if ((ligne[car]==SPACE_ASCII_CODE)||(ligne[car]==TAB_ASCII_CODE))
							slash=0;
						else
						{
							sscanf(ligne+car,"%i",face+slash+ind*3);
							//Console::print("Sommet #%i,%i = %i\n",ind,slash,face[slash+ind*3]);
							if (slash==0) ++ind;

							while ((ligne[car+1]>0)&&(ligne[car+1]!=SPACE_ASCII_CODE)&&(ligne[car+1]!=TAB_ASCII_CODE)) ++car;
						}
					}

					++car;
				}

				//system("PAUSE");

				//on a normalement 'ind' sommets
				for (j=0;j<ind-2;++j)
				{
					assert(face[0]-1<vertexes->size());
					assert(face[j*3+3]-1<vertexes->size());
					assert(face[j*3+6]-1<vertexes->size());
					if (theoricNumberOfFaces==facesReaded)
					{
						theoricNumberOfFaces+=MAX_NUMBER_OF_ELEMENTS_PER_CHUNK;
						tri->reserve(theoricNumberOfFaces);
					}
					tri->addTriangle(face[0]-1,face[j*3+3]-1,face[j*3+6]-1);
					++facesReaded;
				}
			}
		}
	}

	delete[] face;

	if (vertexes->size()==0)
	{
		delete vertexes;
		vertexes=NULL;
	}
	else
	{
		printf("[ObjFilter::loadModelFromObjFile] Points = %i, Faces = %i\n",lineReaded,facesReaded);

		vertexes->resize(lineReaded);
		tri->resize(facesReaded);
	}

	return tri;
}
